﻿using LCA.Community.DAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using LCA.Community.DAL.Model;
using LCA.Community.DAL.Interfaces;
using LCA.Community.DAL.Test.ModelFactories;
using Microsoft.Practices.Unity;

namespace LCA.Community.DAL.Test
{
    
    
    /// <summary>
    ///This is a test class for MessageRepositoryTest and is intended
    ///to contain all MessageRepositoryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class MessagesRepositoryTest : BaseTestClass
    {
        private List<User> _users;
        private UsersFactory _usersFactory = new UsersFactory();
        private GroupsFactory _groupsFactory = new GroupsFactory();
        private List<Group> _groups;
        private List<Message> _messages;
        private List<Message> _helpRequests;
        private MessagesFactory _messagesFactory = new MessagesFactory();
        private MessageRecipentsFactory _messageRecipentsFactory = new MessageRecipentsFactory();

        /// <summary>
        /// Initializes the test.
        /// </summary>
        [TestInitialize()]
        public void InitializeTest()
        {
            UnityContainerInitializer();

            var usersRepository = _unityContainer.Resolve<IUsersRepository>();
            _users = _usersFactory.CreateList(10);
            _groups = _groupsFactory.CreateList(10, _users[0].RowKey);
            _users.ForEach(user => usersRepository.Add(user));

            var messagesRepository = _unityContainer.Resolve<IMessagesRepository>();
            var messagesRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();
            _messages = new List<Message>();
            _helpRequests = new List<Message>();

            var recipents = new List<string> { _users[1].RowKey, _users[2].RowKey, _users[3].RowKey };
            var message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);
            _messages.Add(message);
            messagesRepository.Add(message);

            recipents = new List<string> { _users[1].RowKey, _users[4].RowKey, _users[5].RowKey };
            message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);
            _messages.Add(message);
            messagesRepository.Add(message);

            recipents = new List<string> { _groups[0].RowKey };
            message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);
            message.Subject = messagesRepository.JoiningRequestSubject;
            _messages.Add(message);
            messagesRepository.Add(message);

            recipents = new List<string> { _users[1].RowKey };
            message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);
            message.Subject = messagesRepository.FriendshipRequestSubject;
            _messages.Add(message);
            messagesRepository.Add(message);

            recipents = new List<string> { _users[1].RowKey };
            message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);
            message.Subject = messagesRepository.HelpRequestSubject;
            _messages.Add(message);
            messagesRepository.Add(message);

            message = _messagesFactory.CreateHelpRequest(_users[0].RowKey, _users[6].RowKey);
            _helpRequests.Add(message);
            messagesRepository.Add(message);

            message = _messagesFactory.CreateHelpRequest(_users[1].RowKey, _users[7].RowKey);
            _helpRequests.Add(message);
            messagesRepository.Add(message);
        }

        /// <summary>
        /// Cleans up the test.
        /// </summary>
        [TestCleanup()]
        public void CleanupTest()
        {
            var usersRepository = _unityContainer.Resolve<IUsersRepository>();
            var messagesRepository = _unityContainer.Resolve<IMessagesRepository>();
            var messagesRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();
            usersRepository.DeleteTestEntities();
            messagesRepository.DeleteTestEntities();
            messagesRecipentsRepository.DeleteTestEntities();
        }

        /// <summary>
        ///A test for GetHelpPoolRequests
        ///</summary>
        [TestMethod()]
        public void GetHelpPoolRequestsTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            List<Message> expected = _helpRequests;
            List<Message> actual;

            actual = target.GetHelpPoolRequests();
            CollectionAssert.AreEquivalent(expected, actual);
        }

        /// <summary>
        ///A test for GetMessagesByUser
        ///</summary>
        [TestMethod()]
        public void GetMessagesSentByUserTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            string userID = _users[0].RowKey;
            List<Message> expected = _messages.Where(m => m.User == userID).ToList();
            expected.AddRange(_helpRequests.Where(hr => hr.User == userID));
            List<Message> actual;

            actual = target.GetMessagesSentByUser(userID);
            CollectionAssert.AreEquivalent(expected, actual);
        }

        /// <summary>
        ///A test for GetVolunteerHelpRequests
        ///</summary>
        [TestMethod()]
        public void GetVolunteerHelpRequestsTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            string userID = _users[6].RowKey;
            List<Message> expected = _helpRequests.Where(hr => hr.Recipents.Contains(userID)).ToList();
            List<Message> actual;

            var mr = _unityContainer.Resolve<IMessagesRecipentsRepository>();

            actual = target.GetVolunteerHelpRequests(userID);
            CollectionAssert.AreEquivalent(expected, actual);
        }

        /// <summary>
        ///A test for DeleteAllUserMessages
        ///</summary>
        [TestMethod()]
        public void DeleteAllUserMessagesTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            var messageRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();
            string userID = _users[0].RowKey;

            target.DeleteAllUserMessages(userID);
            var actualMessages = target.GetMessagesSentByUser(userID);
            CollectionAssert.AreEquivalent(new List<Message>(), actualMessages);

            var actualRecipents = messageRecipentsRepository.GetMessageRecipentsByReceiver(userID);
            CollectionAssert.AreEquivalent(new List<MessageRecipent>(), actualRecipents);
        }

        /// <summary>
        ///A test for GetInbox
        ///</summary>
        [TestMethod()]
        public void GetInboxTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            var messageRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();
            string userID = _users[0].RowKey;
            List<Message> expected = _messages.Where(m => m.Recipents.Contains(userID)).ToList();
            List<Message> actual;

            actual = target.GetInbox(userID);
            CollectionAssert.AreEquivalent(expected, actual);
        }

        /// <summary>
        ///A test for GetJoiningRequestMessage
        ///</summary>
        [TestMethod()]
        public void GetJoiningRequestMessageTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            string userID = _users[0].RowKey;
            string groupID = _groups[0].RowKey;
            Message expected = _messages.Where(m => m.Subject == target.JoiningRequestSubject && m.User == userID && m.Recipents.Contains(groupID)).First();

            Message actual;
            actual = target.GetJoiningRequestMessage(groupID, userID);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Add
        ///</summary>
        [TestMethod()]
        public void AddTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            var messageRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();

            var recipents = new List<string> { _users[1].RowKey, _users[2].RowKey, _users[3].RowKey };
            var message = _messagesFactory.CreateEntity(_users[0].RowKey, recipents);

            target.Add(message);

            var actual = target.Get(message.RowKey);
            Assert.AreEqual(actual, message);

             var actualRecipents = messageRecipentsRepository.Entities.Where(mr => mr.Message == message.RowKey).Select(mr => mr.Recipent).ToList();
             CollectionAssert.AreEquivalent(recipents,actualRecipents);
        }

        /// <summary>
        ///A test for Delete
        ///</summary>
        [TestMethod()]
        public void DeleteTest1()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            var messageRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();

            var message = _messages[0];

            target.Delete(message);

            var actualMessage = target.Get(message.RowKey);
            Assert.IsNull(actualMessage);

            var actualRecipents = messageRecipentsRepository.GetMessageRecipentsByMessage(message.RowKey);
            CollectionAssert.AreEquivalent(new List<MessageRecipent>(), actualRecipents);
        }

        /// <summary>
        /// A test for Delete
        ///</summary>
        [TestMethod()]
        public void DeleteTest2()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            var messageRecipentsRepository = _unityContainer.Resolve<IMessagesRecipentsRepository>();

            var message = _messages[0];

            target.Delete(message.RowKey);

            var actualMessage = target.Get(message.RowKey);
            Assert.IsNull(actualMessage);

            var actualRecipents = messageRecipentsRepository.GetMessageRecipentsByMessage(message.RowKey);
            CollectionAssert.AreEquivalent(new List<MessageRecipent>(), actualRecipents);
        }

        /// <summary>
        ///A test for GetFriendshipRequestMessage
        ///</summary>
        [TestMethod()]
        public void GetFriendshipRequestMessageTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            string userID = _users[0].RowKey;
            string friendID = _users[1].RowKey;
            Message expected = _messages.Where(m => m.Subject == target.FriendshipRequestSubject && m.User == userID && m.Recipents.Contains(friendID)).First();

            Message actual;
            actual = target.GetFriendshipRequestMessage(userID, friendID);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetHelpRequest
        ///</summary>
        [TestMethod()]
        public void GetHelpRequestTest()
        {
            var target = _unityContainer.Resolve<IMessagesRepository>();
            string userID = _users[0].RowKey;
            string volunteerID = _users[1].RowKey;
            Message expected = _messages.Where(m => m.Subject == target.HelpRequestSubject && m.User == userID && m.Recipents.Contains(volunteerID)).First();

            Message actual;
            actual = target.GetHelpRequest(userID, volunteerID);
            Assert.AreEqual(expected, actual);
        }
    }
}